/*
 * SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
 *
 * SPDX-License-Identifier: MulanPSL-2.0
 */
#![allow(non_camel_case_types)]
#![allow(unused_variables)]
#![allow(unused_mut)]
#![allow(non_upper_case_globals)]
#![allow(dead_code)]
#![allow(unused_unsafe)]
#![allow(unused_assignments)]
#![allow(clippy::never_loop)]
#![allow(clippy::blocks_in_conditions)]
//used other
use crate::common::*;
//use crate::pwutil_impl::sudo_make_pwitem;
//use crate::pwutil_impl::sudo_make_gritem;
//use crate::pwutil_impl::sudo_make_grlist_item;
//use crate::pwutil_impl::sudo_make_gidlist_item;
use crate::redblack::rbcreate;
use crate::redblack::rbfind;
use crate::redblack::rbinsert;
//use crate::pwutil_impl::cache_item_pw;
use crate::redblack::rbdestroy;

use crate::pwutil_impl::cache_item_gr; //bgz
use crate::pwutil_impl::cache_item_pw; //bgz

//fn externc
extern "C" {
    fn strcasecmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int;

    fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int;
    static mut sudoers_subsystem_ids: [libc::c_uint; 0];
    fn sudo_strtoid_v2(str: *const libc::c_char, errstr: *mut *const libc::c_char) -> id_t;
    static mut sudo_defs_table: [sudo_defs_types; 0];
    fn sudo_debug_printf2_v1(
        func: *const libc::c_char,
        file: *const libc::c_char,
        line: libc::c_int,
        level: libc::c_int,
        fmt: *const libc::c_char,
        _: ...
    );
    fn memcpy(_: *mut libc::c_void, _: *const libc::c_void, _: libc::c_ulong) -> *mut libc::c_void;
    fn strlen(_: *const libc::c_char) -> libc::c_ulong;
    fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void;

    fn __errno_location() -> *mut libc::c_int;

    fn sudo_warn_nodebug_v1(fmt: *const libc::c_char, _: ...);
    fn sudo_strlcpy(dst: *mut libc::c_char, src: *const libc::c_char, siz: size_t) -> size_t;
    fn sudo_warnx_nodebug_v1(fmt: *const libc::c_char, _: ...);
    fn sudo_make_gritem(gid: gid_t, group: *const libc::c_char) -> *mut cache_item;
    fn sudo_make_grlist_item(
        pw: *const passwd,
        groups: *const *mut libc::c_char,
    ) -> *mut cache_item;
    fn sudo_make_gidlist_item(
        pw: *const passwd,
        gids: *const *mut libc::c_char,
        type_0: libc::c_uint,
    ) -> *mut cache_item;
    fn sudo_make_pwitem(uid: uid_t, user: *const libc::c_char) -> *mut cache_item;
}

//typedef
pub type gid_t = libc::c_uint;

//constants
pub type sudo_make_pwitem_t =
    Option<unsafe extern "C" fn(uid_t, *const libc::c_char) -> *mut cache_item>;
pub type sudo_make_gritem_t =
    Option<unsafe extern "C" fn(gid_t, *const libc::c_char) -> *mut cache_item>;
pub type sudo_make_gidlist_item_t = Option<
    unsafe extern "C" fn(*const passwd, *const *mut libc::c_char, libc::c_uint) -> *mut cache_item,
>;
pub type sudo_make_grlist_item_t =
    Option<unsafe extern "C" fn(*const passwd, *const *mut libc::c_char) -> *mut cache_item>;
static mut pwcache_byuid: *mut rbtree = 0 as *const rbtree as *mut rbtree;
static mut pwcache_byname: *mut rbtree = 0 as *const rbtree as *mut rbtree;
static mut grcache_bygid: *mut rbtree = 0 as *const rbtree as *mut rbtree;
static mut grcache_byname: *mut rbtree = 0 as *const rbtree as *mut rbtree;
static mut gidlist_cache: *mut rbtree = 0 as *const rbtree as *mut rbtree;
static mut grlist_cache: *mut rbtree = 0 as *const rbtree as *mut rbtree;

static mut make_pwitem: sudo_make_pwitem_t = unsafe {
    Some(sudo_make_pwitem as unsafe extern "C" fn(uid_t, *const libc::c_char) -> *mut cache_item)
};

static mut make_gritem: sudo_make_gritem_t = unsafe {
    Some(sudo_make_gritem as unsafe extern "C" fn(gid_t, *const libc::c_char) -> *mut cache_item)
};

static mut make_gidlist_item: sudo_make_gidlist_item_t = unsafe {
    Some(
        sudo_make_gidlist_item
            as unsafe extern "C" fn(
                *const passwd,
                *const *mut libc::c_char,
                libc::c_uint,
            ) -> *mut cache_item,
    )
};

static mut make_grlist_item: sudo_make_grlist_item_t = unsafe {
    Some(
        sudo_make_grlist_item
            as unsafe extern "C" fn(*const passwd, *const *mut libc::c_char) -> *mut cache_item,
    )
};

pub const ENTRY_TYPE_ANY: libc::c_int = 0;
pub const ENOENT: libc::c_int = 2;

//structs
#[derive(Copy, Clone)]
#[repr(C)]
pub struct gid_list {
    pub ngids: libc::c_int,
    pub gids: *mut gid_t,
}

//write_functions
unsafe extern "C" fn cmp_pwuid(
    mut v1: *const libc::c_void,
    mut v2: *const libc::c_void,
) -> libc::c_int {
    let mut ci1: *const cache_item = v1 as *const cache_item;
    let mut ci2: *const cache_item = v2 as *const cache_item;
    if (*ci1).k.uid == (*ci2).k.uid {
        return strcmp(((*ci1).registry).as_ptr(), ((*ci2).registry).as_ptr());
    }
    if (*ci1).k.uid < (*ci2).k.uid {
        return -(1 as libc::c_int);
    }
    1 as libc::c_int
}

unsafe extern "C" fn cmp_pwnam(
    mut v1: *const libc::c_void,
    mut v2: *const libc::c_void,
) -> libc::c_int {
    let mut ci1: *const cache_item = v1 as *const cache_item;
    let mut ci2: *const cache_item = v2 as *const cache_item;
    let mut ret: libc::c_int = strcmp((*ci1).k.name, (*ci2).k.name);
    if ret == 0 as libc::c_int {
        ret = strcmp(((*ci1).registry).as_ptr(), ((*ci2).registry).as_ptr());
    }
    ret
}

unsafe extern "C" fn cmp_grgid(
    mut v1: *const libc::c_void,
    mut v2: *const libc::c_void,
) -> libc::c_int {
    let mut ci1: *const cache_item = v1 as *const cache_item;
    let mut ci2: *const cache_item = v2 as *const cache_item;
    if (*ci1).k.gid == (*ci2).k.gid {
        return strcmp(((*ci1).registry).as_ptr(), ((*ci2).registry).as_ptr());
    }
    if (*ci1).k.gid < (*ci2).k.gid {
        return -(1 as libc::c_int);
    }
    1 as libc::c_int
}

#[no_mangle]
pub fn sudo_pwutil_set_backend(
    mut pwitem: sudo_make_pwitem_t,
    mut gritem: sudo_make_gritem_t,
    mut gidlist_item: sudo_make_gidlist_item_t,
    mut grlist_item: sudo_make_grlist_item_t,
) {
    unsafe {
        debug_decl!(SUDOERS_DEBUG_NSS!());

        make_pwitem = pwitem;
        make_gritem = gritem;
        make_gidlist_item = gidlist_item;
        make_grlist_item = grlist_item;

        debug_return!();
    } //unsafe
}

unsafe extern "C" fn cmp_gidlist(
    mut v1: *const libc::c_void,
    mut v2: *const libc::c_void,
) -> libc::c_int {
    let mut ci1: *const cache_item = v1 as *const cache_item;
    let mut ci2: *const cache_item = v2 as *const cache_item;
    let mut ret: libc::c_int = strcmp((*ci1).k.name, (*ci2).k.name);
    if ret == 0 as libc::c_int {
        if (*ci1).type_0 == ENTRY_TYPE_ANY as libc::c_int as libc::c_uint
            || (*ci1).type_0 == (*ci2).type_0
        {
            return strcmp(((*ci1).registry).as_ptr(), ((*ci2).registry).as_ptr());
        }
        if (*ci1).type_0 < (*ci2).type_0 {
            return -(1 as libc::c_int);
        }
        return 1 as libc::c_int;
    }
    ret
}

#[no_mangle]
pub fn sudo_pw_addref(mut pw: *mut passwd) {
    unsafe {
        debug_decl!(SUDOERS_DEBUG_NSS!());

        let fresh0 = &mut (*((pw as *mut libc::c_char).offset(-(40 as libc::c_ulong as isize))
            as *mut cache_item))
            .refcnt;
        *fresh0 = (*fresh0).wrapping_add(1);

        debug_return!();
    } //unsafe
}

unsafe extern "C" fn sudo_pw_delref_item(mut v: *mut libc::c_void) {
    let mut item: *mut cache_item = v as *mut cache_item;
    debug_decl!(SUDOERS_DEBUG_NSS!());

    let fresh1 = &mut (*item).refcnt;
    *fresh1 = (*fresh1).wrapping_sub(1);
    if *fresh1 == 0 as libc::c_int as libc::c_uint {
        free(item as *mut libc::c_void);
    }

    debug_return!();
}

#[no_mangle]
pub fn sudo_gidlist_addref(mut gidlist: *mut gid_list) {
    unsafe {
        debug_decl!(SUDOERS_DEBUG_NSS!());
        let fresh24 =
            &mut (*((gidlist as *mut libc::c_char).offset(-(40 as libc::c_ulong as isize))
                as *mut cache_item))
                .refcnt;
        *fresh24 = (*fresh24).wrapping_add(1);
        debug_return!();
    }
}

#[no_mangle]
pub fn sudo_pw_delref(mut pw: *mut passwd) {
    unsafe {
        debug_decl!(SUDOERS_DEBUG_NSS!());
        sudo_pw_delref_item(
            (pw as *mut libc::c_char).offset(-(40 as libc::c_ulong as isize)) as *mut cache_item
                as *mut libc::c_void,
        );
        debug_return!();
    } //unsafe
}

/*
#[no_mangle]
pub unsafe extern "C" fn sudo_getpwnam(mut name: *const libc::c_char) -> *mut passwd {
    let mut item: *mut passwd = 0 as *mut passwd;

    return item;
}
*/

///////////////////////////
#[no_mangle]
pub fn sudo_get_grlist(mut pw: *const passwd) -> *mut group_list {
    let mut key: cache_item = cache_item {
        refcnt: 0,
        type_0: 0,
        registry: [0; 16],
        k: cache_item_key_union { uid: 0 },
        d: cache_item_datum_union {
            pw: std::ptr::null_mut::<passwd>(),
        },
    };
    let mut item: *mut cache_item = std::ptr::null_mut::<cache_item>();
    let mut node: *mut rbnode = std::ptr::null_mut::<rbnode>();
    unsafe {
        debug_decl!(SUDOERS_DEBUG_NSS!());

        sudo_debug_printf!(
            SUDO_DEBUG_DEBUG,
            b"%s: looking up group names for %s\0" as *const u8 as *const libc::c_char,
            get_function_name!(),
            (*pw).pw_name
        );

        if grlist_cache.is_null() {
            grlist_cache = rbcreate(Some(
                cmp_pwnam
                    as unsafe extern "C" fn(
                        *const libc::c_void,
                        *const libc::c_void,
                    ) -> libc::c_int,
            ));

            if grlist_cache.is_null() {
                sudo_warnx!(
                    b"%s: %s\0" as *const u8 as *const libc::c_char,
                    get_function_name!(),
                    b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                );
                debug_return_ptr!(std::ptr::null_mut::<group_list>());
            }
        }
        //wait write line 204

        'done: loop {
            key.k.name = (*pw).pw_name;
            key.registry[0 as libc::c_int as usize] = '\u{0}' as i32 as libc::c_char;
            node = rbfind(
                grlist_cache,
                &mut key as *mut cache_item as *mut libc::c_void,
            );
            if !node.is_null() {
                item = (*node).data as *mut cache_item;
                break 'done;
            }

            item = make_grlist_item.expect("non-null function pointer")(
                pw,
                std::ptr::null::<*mut libc::c_char>(),
            );

            if item.is_null() {
                debug_return_ptr!(std::ptr::null_mut::<group_list>());
            }

            sudo_strlcpy(
                ((*item).registry).as_mut_ptr(),
                (key.registry).as_mut_ptr(),
                ::std::mem::size_of::<[libc::c_char; 16]>() as libc::c_ulong,
            );

            match rbinsert(
                grlist_cache,
                item as *mut libc::c_void,
                std::ptr::null_mut::<*mut rbnode>(),
            ) as libc::c_int
            {
                1 => {
                    sudo_warnx!(
                        b"unable to cache group list for %s, already exists\0" as *const u8
                            as *const libc::c_char,
                        (*pw).pw_name
                    );
                    (*item).refcnt = 0 as libc::c_int as libc::c_uint;
                }
                -1 => {
                    sudo_warn!(
                        b"unable to cache group list for %s\0" as *const u8 as *const libc::c_char,
                        (*pw).pw_name
                    );
                    (*item).refcnt = 0 as libc::c_int as libc::c_uint;
                }
                _ => {}
            }

            if !((*item).d.grlist).is_null() {
                let mut i: libc::c_int = 0;
                i = 0 as libc::c_int;
                while i < (*(*item).d.grlist).ngroups {
                    sudo_debug_printf!(
                        SUDO_DEBUG_DEBUG,
                        b"%s: user %s is a member of group %s\0" as *const u8
                            as *const libc::c_char,
                        get_function_name!(),
                        (*pw).pw_name,
                        *((*(*item).d.grlist).groups).offset(i as isize)
                    );
                    i += 1;
                }
            }
            break 'done;
        }

        if !((*item).d.grlist).is_null() {
            let fresh28 = &mut (*item).refcnt;
            *fresh28 = (*fresh28).wrapping_add(1);
        }
        debug_return_ptr!((*item).d.grlist);
    } //unsafe
}
/////////////////////////
#[no_mangle]
pub fn sudo_get_gidlist(mut pw: *const passwd, mut type_0: libc::c_uint) -> *mut gid_list {
    let mut key: cache_item = cache_item {
        refcnt: 0,
        type_0: 0,
        registry: [0; 16],
        k: cache_item_key_union { uid: 0 },
        d: cache_item_datum_union {
            pw: std::ptr::null_mut::<passwd>(),
        },
    };
    let mut item: *mut cache_item = std::ptr::null_mut::<cache_item>();
    let mut node: *mut rbnode = std::ptr::null_mut::<rbnode>();
    unsafe {
        debug_decl!(SUDOERS_DEBUG_NSS!());

        sudo_debug_printf!(
            SUDO_DEBUG_DEBUG,
            b"%s: looking up group-IDs for %s\0" as *const u8 as *const libc::c_char,
            get_function_name!(),
            (*pw).pw_name
        );

        if gidlist_cache.is_null() {
            gidlist_cache = rbcreate(Some(
                cmp_gidlist
                    as unsafe extern "C" fn(
                        *const libc::c_void,
                        *const libc::c_void,
                    ) -> libc::c_int,
            ));

            if gidlist_cache.is_null() {
                sudo_warnx!(
                    b"%s: %s\0" as *const u8 as *const libc::c_char,
                    get_function_name!(),
                    b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                );
                debug_return_ptr!(std::ptr::null_mut::<gid_list>());
            }
        }

        'done: loop {
            key.k.name = (*pw).pw_name;
            key.type_0 = type_0;
            key.registry[0 as libc::c_int as usize] = '\u{0}' as i32 as libc::c_char;
            node = rbfind(
                gidlist_cache,
                &mut key as *mut cache_item as *mut libc::c_void,
            );
            if !node.is_null() {
                item = (*node).data as *mut cache_item;
                break 'done;
            }

            item = make_gidlist_item.expect("non-null function pointer")(
                pw,
                std::ptr::null::<*mut libc::c_char>(),
                type_0,
            );

            if item.is_null() {
                debug_return_ptr!(std::ptr::null_mut::<gid_list>());
            }

            sudo_strlcpy(
                ((*item).registry).as_mut_ptr(),
                (key.registry).as_mut_ptr(),
                ::std::mem::size_of::<[libc::c_char; 16]>() as libc::c_ulong,
            );

            match rbinsert(
                gidlist_cache,
                item as *mut libc::c_void,
                std::ptr::null_mut::<*mut rbnode>(),
            ) as libc::c_int
            {
                1 => {
                    sudo_warnx!(
                        b"unable to cache group list for %s, already exists\0" as *const u8
                            as *const libc::c_char,
                        (*pw).pw_name
                    );
                    (*item).refcnt = 0 as libc::c_int as libc::c_uint;
                }
                -1 => {
                    sudo_warn!(
                        b"unable to cache group list for %s\0" as *const u8 as *const libc::c_char,
                        (*pw).pw_name
                    );
                    (*item).refcnt = 0 as libc::c_int as libc::c_uint;
                }
                _ => {}
            }

            if !((*item).d.gidlist).is_null() {
                let mut i: libc::c_int = 0;
                i = 0 as libc::c_int;
                while i < (*(*item).d.gidlist).ngids {
                    sudo_debug_printf!(
                        SUDO_DEBUG_DEBUG,
                        b"%s: user %s has supplementary gid %u\0" as *const u8
                            as *const libc::c_char,
                        get_function_name!(),
                        (*pw).pw_name,
                        *((*(*item).d.gidlist).gids).offset(i as isize)
                    );
                    i += 1;
                }
            }
            break 'done;
        }

        if !((*item).d.gidlist).is_null() {
            let fresh28 = &mut (*item).refcnt;
            *fresh28 = (*fresh28).wrapping_add(1);
        }
        debug_return_ptr!((*item).d.gidlist as *mut gid_list);
    } //unsafe
}
////////////////////////

#[no_mangle]
pub fn sudo_getpwuid(mut uid: uid_t) -> *mut passwd {
    let mut key: cache_item = cache_item {
        refcnt: 0,
        type_0: 0,
        registry: [0; 16],
        k: cache_item_key_union { uid: 0 },
        d: cache_item_datum_union {
            pw: std::ptr::null_mut::<passwd>(),
        },
    };
    let mut item: *mut cache_item = std::ptr::null_mut::<cache_item>();
    let mut node: *mut rbnode = std::ptr::null_mut::<rbnode>();
    unsafe {
        debug_decl!(SUDOERS_DEBUG_NSS!());

        if pwcache_byuid.is_null() {
            pwcache_byuid = rbcreate(Some(
                cmp_pwuid
                    as unsafe extern "C" fn(
                        *const libc::c_void,
                        *const libc::c_void,
                    ) -> libc::c_int,
            ));

            if pwcache_byuid.is_null() {
                sudo_warnx!(
                    b"%s: %s\0" as *const u8 as *const libc::c_char,
                    get_function_name!(),
                    b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                );
                debug_return_ptr!(std::ptr::null_mut::<passwd>());
            }
        }
        //wait write line 204

        'done: loop {
            key.k.uid = uid;
            key.registry[0 as libc::c_int as usize] = '\u{0}' as i32 as libc::c_char;
            node = rbfind(
                pwcache_byuid,
                &mut key as *mut cache_item as *mut libc::c_void,
            );
            if !node.is_null() {
                item = (*node).data as *mut cache_item;
                break 'done;
            }
            /*
             * Cache passwd db entry if it exists or a negative response if not.
             */
            item = make_pwitem.expect("non-null function pointer")(
                uid,
                std::ptr::null::<libc::c_char>(),
            );

            if item.is_null() {
                item = calloc(
                    1 as libc::c_int as libc::c_ulong,
                    ::std::mem::size_of::<cache_item>() as libc::c_ulong,
                ) as *mut cache_item;
                if *__errno_location() != ENOENT as libc::c_int || item.is_null() {
                    sudo_warn!(
                        b"unable to cache uid %u\0" as *const u8 as *const libc::c_char,
                        uid
                    );
                    debug_return_ptr!(std::ptr::null_mut::<passwd>());
                }
                (*item).refcnt = 1 as libc::c_int as libc::c_uint;
                (*item).k.uid = uid;
            }

            sudo_strlcpy(
                ((*item).registry).as_mut_ptr(),
                (key.registry).as_mut_ptr(),
                ::std::mem::size_of::<[libc::c_char; 16]>() as libc::c_ulong,
            );

            match rbinsert(
                pwcache_byuid,
                item as *mut libc::c_void,
                std::ptr::null_mut::<*mut rbnode>(),
            ) as libc::c_int
            {
                1 => {
                    sudo_warnx!(
                        b"unable to cache uid %u, already exists\0" as *const u8
                            as *const libc::c_char,
                        uid
                    );
                    (*item).refcnt = 0 as libc::c_int as libc::c_uint;
                }
                -1 => {
                    sudo_warn!(
                        b"unable to cache uid %u\0" as *const u8 as *const libc::c_char,
                        uid
                    );
                    (*item).refcnt = 0 as libc::c_int as libc::c_uint;
                }
                _ => {}
            }

            break 'done;
        }
        if (*item).refcnt != 0 as libc::c_int as libc::c_uint {
            sudo_debug_printf!(
                SUDO_DEBUG_DEBUG,
                b"%s: uid %u [%s] -> user %s [%s] (%s)\0" as *const u8 as *const libc::c_char,
                get_function_name!(),
                uid,
                (key.registry).as_mut_ptr(),
                if !((*item).d.pw).is_null() {
                    (*(*item).d.pw).pw_name
                } else {
                    b"unknown\0" as *const u8 as *const libc::c_char
                },
                ((*item).registry).as_mut_ptr(),
                if !node.is_null() {
                    b"cache hit\0" as *const u8 as *const libc::c_char
                } else {
                    b"cached\0" as *const u8 as *const libc::c_char
                }
            );
        }
        if !((*item).d.pw).is_null() {
            (*item).refcnt = ((*item).refcnt).wrapping_add(1);
        }
        debug_return_ptr!((*item).d.pw);
    } //unsafe
}

#[no_mangle]
pub fn sudo_getpwnam(mut name: *const libc::c_char) -> *mut passwd {
    let mut key: cache_item = cache_item {
        refcnt: 0,
        type_0: 0,
        registry: [0; 16],
        k: cache_item_key_union { uid: 0 },
        d: cache_item_datum_union {
            pw: std::ptr::null_mut::<passwd>(),
        },
    };
    let mut item: *mut cache_item = std::ptr::null_mut::<cache_item>();
    let mut node: *mut rbnode = std::ptr::null_mut::<rbnode>();
    unsafe {
        debug_decl!(SUDOERS_DEBUG_NSS!());

        if pwcache_byname.is_null() {
            pwcache_byname = rbcreate(Some(
                cmp_pwnam
                    as unsafe extern "C" fn(
                        *const libc::c_void,
                        *const libc::c_void,
                    ) -> libc::c_int,
            ));

            if pwcache_byname.is_null() {
                sudo_warnx!(
                    b"%s: %s\0" as *const u8 as *const libc::c_char,
                    get_function_name!(),
                    b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                );
                debug_return_ptr!(std::ptr::null_mut::<passwd>());
            }
        }

        'done: loop {
            key.k.name = name as *mut libc::c_char;
            key.registry[0 as libc::c_int as usize] = '\u{0}' as i32 as libc::c_char;
            node = rbfind(
                pwcache_byname,
                &mut key as *mut cache_item as *mut libc::c_void,
            );
            if !node.is_null() {
                item = (*node).data as *mut cache_item;
                break 'done;
            }

            item =
                make_pwitem.expect("non-null function pointer")(-(1 as libc::c_int) as uid_t, name);

            if item.is_null() {
                let len: size_t = (strlen(name)).wrapping_add(1 as libc::c_int as libc::c_ulong);
                item = calloc(
                    1 as libc::c_int as libc::c_ulong,
                    (::std::mem::size_of::<cache_item>() as libc::c_ulong).wrapping_add(len),
                ) as *mut cache_item;
                if *__errno_location() != ENOENT as libc::c_int || item.is_null() {
                    sudo_warn!(
                        b"unable to cache user %s\0" as *const u8 as *const libc::c_char,
                        name
                    );
                    debug_return_ptr!(std::ptr::null_mut::<passwd>());
                }
                (*item).refcnt = 1 as libc::c_int as libc::c_uint;
                (*item).k.name = (item as *mut libc::c_char)
                    .offset(::std::mem::size_of::<cache_item>() as libc::c_ulong as isize);
                memcpy(
                    (*item).k.name as *mut libc::c_void,
                    name as *const libc::c_void,
                    len,
                );
            }

            sudo_strlcpy(
                ((*item).registry).as_mut_ptr(),
                (key.registry).as_mut_ptr(),
                ::std::mem::size_of::<[libc::c_char; 16]>() as libc::c_ulong,
            );

            match rbinsert(
                pwcache_byname,
                item as *mut libc::c_void,
                std::ptr::null_mut::<*mut rbnode>(),
            ) as libc::c_int
            {
                1 => {
                    sudo_warnx!(
                        b"unable to cache user %s, already exists\0" as *const u8
                            as *const libc::c_char,
                        name
                    );
                    (*item).refcnt = 0 as libc::c_int as libc::c_uint;
                }
                -1 => {
                    sudo_warn!(
                        b"unable to cache user %s\0" as *const u8 as *const libc::c_char,
                        name
                    );
                    (*item).refcnt = 0 as libc::c_int as libc::c_uint;
                }
                _ => {}
            }

            break 'done;
        }
        if (*item).refcnt != 0 as libc::c_int as libc::c_uint {
            sudo_debug_printf!(
                SUDO_DEBUG_DEBUG,
                b"%s: user %s [%s] -> uid %d [%s] (%s)\0" as *const u8 as *const libc::c_char,
                get_function_name!(),
                name,
                key.registry,
                if !((*item).d.pw).is_null() {
                    (*(*item).d.pw).pw_uid as libc::c_int
                } else {
                    -(1 as libc::c_int)
                },
                ((*item).registry).as_mut_ptr(),
                if !node.is_null() {
                    b"cache hit\0" as *const u8 as *const libc::c_char
                } else {
                    b"cached\0" as *const u8 as *const libc::c_char
                }
            );
        }
        if !((*item).d.pw).is_null() {
            (*item).refcnt = ((*item).refcnt).wrapping_add(1);
        }
        debug_return_ptr!((*item).d.pw);
    } //unsafe
}

#[no_mangle]
pub fn sudo_getgrgid(mut gid: gid_t) -> *mut group {
    let mut key: cache_item = cache_item {
        refcnt: 0,
        type_0: 0,
        registry: [0; 16],
        k: cache_item_key_union { uid: 0 },
        d: cache_item_datum_union {
            pw: std::ptr::null_mut::<passwd>(),
        },
    };
    let mut item: *mut cache_item = std::ptr::null_mut::<cache_item>();
    let mut node: *mut rbnode = std::ptr::null_mut::<rbnode>();
    unsafe {
        debug_decl!(SUDOERS_DEBUG_NSS!());

        if grcache_bygid.is_null() {
            //
            grcache_bygid = rbcreate(
                //
                Some(
                    cmp_grgid
                        as unsafe extern "C" fn(
                            *const libc::c_void,
                            *const libc::c_void,
                        ) -> libc::c_int,
                ),
            );

            if grcache_bygid.is_null() {
                //
                sudo_warnx!(
                    b"%s: %s\0" as *const u8 as *const libc::c_char,
                    get_function_name!(),
                    b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                );
                debug_return_ptr!(std::ptr::null_mut::<group>());
            }
        }

        'done: loop {
            key.k.gid = gid; //
            key.registry[0 as libc::c_int as usize] = '\u{0}' as i32 as libc::c_char;
            node = rbfind(
                grcache_bygid,
                &mut key as *mut cache_item as *mut libc::c_void,
            ); //
            if !node.is_null() {
                item = (*node).data as *mut cache_item;
                break 'done;
            }

            item = make_gritem.expect("non-null function pointer")(
                gid,
                std::ptr::null::<libc::c_char>(),
            ); //

            if item.is_null() {
                item = calloc(
                    1 as libc::c_int as libc::c_ulong,
                    ::std::mem::size_of::<cache_item>() as libc::c_ulong,
                ) as *mut cache_item;
                if *__errno_location() != ENOENT as libc::c_int || item.is_null() {
                    sudo_warn!(
                        b"unable to cache gid %u\0" as *const u8 as *const libc::c_char,
                        gid
                    );
                    debug_return_ptr!(std::ptr::null_mut::<group>());
                }
                (*item).refcnt = 1 as libc::c_int as libc::c_uint;
                (*item).k.gid = gid;
            }

            sudo_strlcpy(
                ((*item).registry).as_mut_ptr(),
                (key.registry).as_mut_ptr(),
                ::std::mem::size_of::<[libc::c_char; 16]>() as libc::c_ulong,
            );

            match rbinsert(
                grcache_bygid,
                item as *mut libc::c_void,
                std::ptr::null_mut::<*mut rbnode>(),
            ) as libc::c_int
            {
                1 => {
                    sudo_warnx!(
                        b"unable to cache gid %u, already exists\0" as *const u8
                            as *const libc::c_char,
                        gid
                    );
                    (*item).refcnt = 0 as libc::c_int as libc::c_uint;
                }
                -1 => {
                    sudo_warn!(
                        b"unable to cache gid %u\0" as *const u8 as *const libc::c_char,
                        gid
                    );
                    (*item).refcnt = 0 as libc::c_int as libc::c_uint;
                }
                _ => {}
            }

            break 'done;
        }
        if (*item).refcnt != 0 as libc::c_int as libc::c_uint {
            sudo_debug_printf!(
                SUDO_DEBUG_DEBUG,
                b"%s: gid %u [%s] -> group %s [%s] (%s)\0" as *const u8 as *const libc::c_char,
                get_function_name!(),
                gid,
                (key.registry).as_mut_ptr(),
                if !((*item).d.gr).is_null() {
                    (*(*item).d.gr).gr_name
                } else {
                    b"unknown\0" as *const u8 as *const libc::c_char
                },
                ((*item).registry).as_mut_ptr(),
                if !node.is_null() {
                    b"cache hit\0" as *const u8 as *const libc::c_char
                } else {
                    b"cached\0" as *const u8 as *const libc::c_char
                }
            );
        }
        (*item).refcnt = ((*item).refcnt).wrapping_add(1);
        debug_return_ptr!((*item).d.gr as *mut libc::c_void as *mut group);
    } //unsafe
}

///////////////////////////////////

#[no_mangle]
pub fn sudo_getgrnam(mut name: *const libc::c_char) -> *mut group {
    let mut key: cache_item = cache_item {
        refcnt: 0,
        type_0: 0,
        registry: [0; 16],
        k: cache_item_key_union { uid: 0 },
        d: cache_item_datum_union {
            pw: std::ptr::null_mut::<passwd>(),
        },
    };
    let mut item: *mut cache_item = std::ptr::null_mut::<cache_item>();
    let mut node: *mut rbnode = std::ptr::null_mut::<rbnode>();
    unsafe {
        debug_decl!(SUDOERS_DEBUG_NSS!());

        if grcache_byname.is_null() {
            //
            grcache_byname = rbcreate(
                //
                Some(
                    cmp_pwnam
                        as unsafe extern "C" fn(
                            *const libc::c_void,
                            *const libc::c_void,
                        ) -> libc::c_int,
                ),
            );

            if grcache_byname.is_null() {
                //
                sudo_warnx!(
                    b"%s: %s\0" as *const u8 as *const libc::c_char,
                    get_function_name!(),
                    b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                );
                debug_return_ptr!(std::ptr::null_mut::<group>());
            }
        }

        'done: loop {
            key.k.name = name as *mut libc::c_char; //
            key.registry[0 as libc::c_int as usize] = '\u{0}' as i32 as libc::c_char;
            node = rbfind(
                grcache_byname,
                &mut key as *mut cache_item as *mut libc::c_void,
            ); //
            if !node.is_null() {
                item = (*node).data as *mut cache_item;
                break 'done;
            }

            item = make_gritem.expect("non-null function pointer")(
                -(1 as libc::c_int) as gid_t,
                name as *const libc::c_char,
            ); //

            if item.is_null() {
                let len: size_t = (strlen(name)).wrapping_add(1 as libc::c_int as libc::c_ulong);
                item = calloc(
                    1 as libc::c_int as libc::c_ulong,
                    (::std::mem::size_of::<cache_item>() as libc::c_ulong).wrapping_add(len),
                ) as *mut cache_item;
                if *__errno_location() != ENOENT as libc::c_int || item.is_null() {
                    sudo_warn!(
                        b"unable to cache group %s\0" as *const u8 as *const libc::c_char,
                        name
                    );
                    debug_return_ptr!(std::ptr::null_mut::<group>());
                }
                (*item).refcnt = 1 as libc::c_int as libc::c_uint;
                (*item).k.name = (item as *mut libc::c_char)
                    .offset(::std::mem::size_of::<cache_item>() as libc::c_ulong as isize);
                memcpy(
                    (*item).k.name as *mut libc::c_void,
                    name as *const libc::c_void,
                    len,
                );
            }

            sudo_strlcpy(
                ((*item).registry).as_mut_ptr(),
                (key.registry).as_mut_ptr(),
                ::std::mem::size_of::<[libc::c_char; 16]>() as libc::c_ulong,
            );

            match rbinsert(
                grcache_byname,
                item as *mut libc::c_void,
                std::ptr::null_mut::<*mut rbnode>(),
            ) as libc::c_int
            {
                1 => {
                    sudo_warnx!(
                        b"unable to cache group %s, already exists\0" as *const u8
                            as *const libc::c_char,
                        name
                    );
                    (*item).refcnt = 0 as libc::c_int as libc::c_uint;
                }
                -1 => {
                    sudo_warn!(
                        b"unable to cache group %s\0" as *const u8 as *const libc::c_char,
                        name
                    );
                    (*item).refcnt = 0 as libc::c_int as libc::c_uint;
                }
                _ => {}
            }

            break 'done;
        }
        if (*item).refcnt != 0 as libc::c_int as libc::c_uint {
            sudo_debug_printf!(
                SUDO_DEBUG_DEBUG,
                b"%s: group %s [%s] -> gid %d [%s] (%s)\0" as *const u8 as *const libc::c_char,
                get_function_name!(),
                name,
                key.registry,
                if !((*item).d.gr).is_null() {
                    (*(*item).d.gr).gr_gid as libc::c_int
                } else {
                    -(1 as libc::c_int)
                },
                ((*item).registry).as_mut_ptr(),
                if !node.is_null() {
                    b"cache hit\0" as *const u8 as *const libc::c_char
                } else {
                    b"cached\0" as *const u8 as *const libc::c_char
                }
            );
        }
        if !((*item).d.gr).is_null() {
            (*item).refcnt = ((*item).refcnt).wrapping_add(1);
        }
        debug_return_ptr!((*item).d.gr);
    } //unsafe
}

#[no_mangle]
pub fn sudo_set_grlist(mut pw: *mut passwd, mut groups: *const *mut libc::c_char) -> libc::c_int {
    let mut key: cache_item = cache_item {
        refcnt: 0,
        type_0: 0,
        registry: [0; 16],
        k: cache_item_key_union { uid: 0 },
        d: cache_item_datum_union {
            pw: std::ptr::null_mut::<passwd>(),
        },
    };
    let mut item: *mut cache_item = std::ptr::null_mut::<cache_item>();
    let mut node: *mut rbnode = std::ptr::null_mut::<rbnode>();
    unsafe {
        debug_decl!(SUDOERS_DEBUG_NSS!());

        if grlist_cache.is_null() {
            //
            grlist_cache = rbcreate(
                //
                Some(
                    cmp_pwnam
                        as unsafe extern "C" fn(
                            *const libc::c_void,
                            *const libc::c_void,
                        ) -> libc::c_int,
                ),
            );

            if grlist_cache.is_null() {
                //
                sudo_warnx!(
                    b"%s: %s\0" as *const u8 as *const libc::c_char,
                    get_function_name!(),
                    b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                );
                debug_return_int!(-1 as libc::c_int);
            }
        }

        key.k.name = (*pw).pw_name as *mut libc::c_char; //
        key.registry[0 as libc::c_int as usize] = '\u{0}' as i32 as libc::c_char;
        node = rbfind(
            grcache_byname,
            &mut key as *mut cache_item as *mut libc::c_void,
        ); //
        if !node.is_null() {
            item = make_grlist_item.expect("non-null function pointer")(pw, groups);
            if item.is_null() {
                sudo_warnx!(
                    b"unable to cache group list for %s,already exists\0" as *const u8
                        as *const libc::c_char,
                    (*pw).pw_name
                );
                debug_return_int!(-1 as libc::c_int);
            }
            sudo_strlcpy(
                ((*item).registry).as_mut_ptr(),
                (key.registry).as_mut_ptr(),
                ::std::mem::size_of::<[libc::c_char; 16]>() as libc::c_ulong,
            );

            match rbinsert(
                grlist_cache,
                item as *mut libc::c_void,
                std::ptr::null_mut::<*mut rbnode>(),
            ) {
                1 => {
                    sudo_warnx!(
                        b"unable to cache group list for %s,already exists\0" as *const u8
                            as *const libc::c_char,
                        (*pw).pw_name
                    );
                    sudo_grlist_delref_item(item as *mut libc::c_void);
                }
                -1 => {
                    sudo_warn!(
                        b"unable to cache group list for %s\0" as *const u8 as *const libc::c_char,
                        (*pw).pw_name
                    );
                    sudo_grlist_delref_item(item as *mut libc::c_void);
                }
                _ => {}
            }
        }
        debug_return_int!(0 as libc::c_int);
    } //unsafe
}
//////////////////
#[no_mangle]
pub fn sudo_set_gidlist(
    mut pw: *mut passwd,
    mut gids: *const *mut libc::c_char,
    mut type_0: libc::c_uint,
) -> libc::c_int {
    let mut key: cache_item = cache_item {
        refcnt: 0,
        type_0: 0,
        registry: [0; 16],
        k: cache_item_key_union { uid: 0 },
        d: cache_item_datum_union {
            pw: std::ptr::null_mut::<passwd>(),
        },
    };
    let mut item: *mut cache_item = std::ptr::null_mut::<cache_item>();
    let mut node: *mut rbnode = std::ptr::null_mut::<rbnode>();
    unsafe {
        debug_decl!(SUDOERS_DEBUG_NSS!());

        if gidlist_cache.is_null() {
            //
            gidlist_cache = rbcreate(
                //
                Some(
                    cmp_gidlist
                        as unsafe extern "C" fn(
                            *const libc::c_void,
                            *const libc::c_void,
                        ) -> libc::c_int,
                ),
            );

            if gidlist_cache.is_null() {
                //
                sudo_warnx!(
                    b"%s: %s\0" as *const u8 as *const libc::c_char,
                    get_function_name!(),
                    b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                );
                debug_return_int!(-1 as libc::c_int);
            }
        }

        key.k.name = (*pw).pw_name as *mut libc::c_char; //
        key.type_0 = type_0;
        key.registry[0 as libc::c_int as usize] = '\u{0}' as i32 as libc::c_char;
        node = rbfind(
            gidlist_cache,
            &mut key as *mut cache_item as *mut libc::c_void,
        ); //
        if !node.is_null() {
            item = make_gidlist_item.expect("non-null function pointer")(pw, gids, type_0);
            if item.is_null() {
                sudo_warnx!(
                    b"unable to parse gids for %s\0" as *const u8 as *const libc::c_char,
                    (*pw).pw_name
                );
                debug_return_int!(-1 as libc::c_int);
            }
            sudo_strlcpy(
                ((*item).registry).as_mut_ptr(),
                (key.registry).as_mut_ptr(),
                ::std::mem::size_of::<[libc::c_char; 16]>() as libc::c_ulong,
            );

            match rbinsert(
                gidlist_cache,
                item as *mut libc::c_void,
                std::ptr::null_mut::<*mut rbnode>(),
            ) {
                1 => {
                    sudo_warnx!(
                        b"unable to cache group list for %s,already exists\0" as *const u8
                            as *const libc::c_char,
                        (*pw).pw_name
                    );
                    sudo_grlist_delref_item(item as *mut libc::c_void);
                }
                -1 => {
                    sudo_warn!(
                        b"unable to cache group list for %s\0" as *const u8 as *const libc::c_char,
                        (*pw).pw_name
                    );
                    sudo_grlist_delref_item(item as *mut libc::c_void);
                }
                _ => {}
            }
        }
        debug_return_int!(0 as libc::c_int);
    } //unsafe
}
/////////////////////

#[no_mangle]
pub fn sudo_mkpwent(
    mut user: *const libc::c_char,
    mut uid: uid_t,
    mut gid: gid_t,
    mut home: *const libc::c_char,
    mut shell: *const libc::c_char,
) -> *mut passwd {
    let mut pwitem: *mut cache_item_pw = std::ptr::null_mut::<cache_item_pw>();
    let mut item: *mut cache_item = std::ptr::null_mut::<cache_item>();
    let mut pw: *mut passwd = std::ptr::null_mut::<passwd>();
    let mut len: size_t = 0;
    let mut name_len: size_t = 0;
    let mut home_len: size_t = 0;
    let mut shell_len: size_t = 0;
    let mut i: libc::c_int = 0;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_NSS!());

        if pwcache_byuid.is_null() {
            pwcache_byuid = rbcreate(Some(
                cmp_pwuid
                    as unsafe extern "C" fn(
                        *const libc::c_void,
                        *const libc::c_void,
                    ) -> libc::c_int,
            ));
        }
        if pwcache_byname.is_null() {
            pwcache_byname = rbcreate(Some(
                cmp_pwnam
                    as unsafe extern "C" fn(
                        *const libc::c_void,
                        *const libc::c_void,
                    ) -> libc::c_int,
            ));
        }

        if pwcache_byuid.is_null() || pwcache_byname.is_null() {
            sudo_warnx!(
                b"%s: %s\0" as *const u8 as *const libc::c_char,
                get_function_name!(),
                b"unable to allocate memory\0" as *const u8 as *const libc::c_char
            );
            debug_return_ptr!(std::ptr::null_mut::<passwd>());
        }
        /* Optional arguments. */
        if home.is_null() {
            home = b"/\0" as *const u8 as *const libc::c_char;
        }
        if shell.is_null() {
            shell = b"/bin/sh\0" as *const u8 as *const libc::c_char;
        }

        sudo_debug_printf!(
            SUDO_DEBUG_DEBUG,
            b"%s: creating and cashing passwd struct for %s:%u:%u:%s:%s\0" as *const u8
                as *const libc::c_char,
            get_function_name!(),
            user,
            uid,
            gid,
            home,
            shell
        );

        name_len = strlen(user);
        home_len = strlen(home);
        shell_len = strlen(shell);

        len = (::std::mem::size_of::<cache_item_pw>() as libc::c_ulong)
            .wrapping_add(name_len)
            .wrapping_add(1 as libc::c_int as libc::c_ulong)
            .wrapping_add(::std::mem::size_of::<[libc::c_char; 2]>() as libc::c_ulong)
            .wrapping_add(::std::mem::size_of::<[libc::c_char; 1]>() as libc::c_ulong)
            .wrapping_add(home_len)
            .wrapping_add(1 as libc::c_int as libc::c_ulong)
            .wrapping_add(shell_len)
            .wrapping_add(1 as libc::c_int as libc::c_ulong);

        i = 0 as libc::c_int;
        while i < 2 as libc::c_int {
            let mut pwcache: *mut rbtree = std::ptr::null_mut::<rbtree>();
            let mut node: *mut rbnode = std::ptr::null_mut::<rbnode>();
            pwitem = calloc(1 as libc::c_int as libc::c_ulong, len) as *mut cache_item_pw;

            if pwitem.is_null() {
                sudo_warn!(
                    b"unable to cache user %s\0" as *const u8 as *const libc::c_char,
                    user
                );
                debug_return_ptr!(std::ptr::null_mut::<passwd>());
            }

            pw = &mut (*pwitem).pw as *mut passwd;
            (*pw).pw_uid = uid;
            (*pw).pw_gid = gid;
            (*pw).pw_name = pwitem.offset(1 as libc::c_int as isize) as *mut libc::c_char;
            memcpy(
                (*pw).pw_name as *mut libc::c_void,
                user as *const libc::c_void,
                name_len.wrapping_add(1 as libc::c_int as libc::c_ulong),
            );
            (*pw).pw_passwd = ((*pw).pw_name)
                .offset(name_len as isize)
                .offset(1 as libc::c_int as isize);
            memcpy(
                (*pw).pw_passwd as *mut libc::c_void,
                b"*\0" as *const u8 as *const libc::c_char as *const libc::c_void,
                2 as libc::c_int as libc::c_ulong,
            );
            (*pw).pw_gecos = ((*pw).pw_passwd).offset(2 as libc::c_int as isize);
            *((*pw).pw_gecos).offset(0 as libc::c_int as isize) = '\u{0}' as i32 as libc::c_char;
            (*pw).pw_dir = ((*pw).pw_gecos).offset(1 as libc::c_int as isize);
            memcpy(
                (*pw).pw_dir as *mut libc::c_void,
                home as *const libc::c_void,
                home_len.wrapping_add(1 as libc::c_int as libc::c_ulong),
            );
            (*pw).pw_shell = ((*pw).pw_dir)
                .offset(home_len as isize)
                .offset(1 as libc::c_int as isize);
            memcpy(
                (*pw).pw_shell as *mut libc::c_void,
                shell as *const libc::c_void,
                shell_len.wrapping_add(1 as libc::c_int as libc::c_ulong),
            );

            item = &mut (*pwitem).cache;
            (*item).refcnt = 1 as libc::c_int as libc::c_uint;
            (*item).d.pw = pw;
            if i == 0 as libc::c_int {
                (*item).k.uid = (*pw).pw_uid;
                pwcache = pwcache_byuid;
            } else {
                (*item).k.name = (*pw).pw_name;
                pwcache = pwcache_byname;
            }

            //line_c 406
            (*item).registry[0 as libc::c_int as usize] = '\u{0}' as i32 as libc::c_char;
            match rbinsert(pwcache, item as *mut libc::c_void, &mut node) {
                1 => {
                    item = (*node).data as *mut cache_item;
                    if ((*item).d.pw).is_null() {
                        sudo_pw_delref_item(item as *mut libc::c_void);
                        (*node).data = &mut (*pwitem).cache as *mut cache_item as *mut libc::c_void;
                        item = (*node).data as *mut cache_item;
                    } else {
                        free(pwitem as *mut libc::c_void);
                    }
                }
                -1 => {
                    sudo_warn!(
                        b"unable to cache user %s\0" as *const u8 as *const libc::c_char,
                        user
                    );
                    (*item).refcnt = 0 as libc::c_int as libc::c_uint;
                }
                _ => {}
            }

            i += 1;
        } // end of while

        (*item).refcnt = (*item).refcnt.wrapping_add(1);
        debug_return_ptr!((*item).d.pw);
    } //unsafe
}

unsafe extern "C" fn sudo_gidlist_delref_item(mut v: *mut libc::c_void) {
    let mut item: *mut cache_item = v as *mut cache_item;
    debug_decl!(SUDOERS_DEBUG_NSS!());

    let fresh25 = &mut (*item).refcnt;
    *fresh25 = (*fresh25).wrapping_sub(1);
    if *fresh25 == 0 as libc::c_int as libc::c_uint {
        free(item as *mut libc::c_void);
    }

    debug_return!();
}

#[no_mangle]
pub fn sudo_gidlist_delref(mut gidlist: *mut gid_list) {
    unsafe {
        debug_decl!(SUDOERS_DEBUG_NSS!());
        sudo_gidlist_delref_item(
            (gidlist as *mut libc::c_char).offset(-(40 as libc::c_ulong as isize))
                as *mut cache_item as *mut libc::c_void,
        );
        debug_return!();
    } //unsafe
}

#[no_mangle]
pub fn sudo_gr_delref(mut gr: *mut group) {
    unsafe {
        debug_decl!(SUDOERS_DEBUG_NSS!());
        sudo_gr_delref_item(
            (gr as *mut libc::c_char).offset(-(40 as libc::c_ulong as isize)) as *mut cache_item
                as *mut libc::c_void,
        );
        debug_return!();
    } //unsafe
}

#[no_mangle]
pub fn sudo_fakepwnam(mut user: *const libc::c_char, mut gid: gid_t) -> *mut passwd {
    let mut errstr: *const libc::c_char = std::ptr::null::<libc::c_char>();
    let mut uid: uid_t = 0;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_NSS!());

        uid = sudo_strtoid_v2(user.offset(1 as libc::c_int as isize), &mut errstr);
        if !errstr.is_null() {
            sudo_debug_printf!(
                SUDO_DEBUG_DIAG | SUDO_DEBUG_LINENO,
                b"uid %s %s\0" as *const u8 as *const libc::c_char,
                user,
                errstr
            );
            debug_return_ptr!(std::ptr::null_mut::<passwd>());
        }
        debug_return_ptr!(sudo_mkpwent(
            user,
            uid,
            gid,
            std::ptr::null::<libc::c_char>(),
            std::ptr::null::<libc::c_char>()
        ));
    } //unsafe
}

#[no_mangle]
pub fn sudo_freepwcache() {
    unsafe {
        debug_decl!(SUDOERS_DEBUG_NSS!());
        if !pwcache_byuid.is_null() {
            rbdestroy(
                pwcache_byuid,
                Some(sudo_pw_delref_item as unsafe extern "C" fn(*mut libc::c_void) -> ()),
            );
            pwcache_byuid = std::ptr::null_mut::<rbtree>();
        }
        if !pwcache_byname.is_null() {
            rbdestroy(
                pwcache_byname,
                Some(sudo_pw_delref_item as unsafe extern "C" fn(*mut libc::c_void) -> ()),
            );
            pwcache_byname = std::ptr::null_mut::<rbtree>();
        }
        debug_return!();
    } //unsafe
}

#[no_mangle]
pub fn sudo_gr_addref(mut gr: *mut group) {
    unsafe {
        debug_decl!(SUDOERS_DEBUG_NSS!());
        let fresh14 = &mut (*((gr as *mut libc::c_char).offset(-(40 as libc::c_ulong as isize))
            as *mut cache_item))
            .refcnt;
        *fresh14 = (*fresh14).wrapping_add(1);
        debug_return!();
    } //unsafe
}

unsafe extern "C" fn sudo_gr_delref_item(mut v: *mut libc::c_void) {
    let mut item: *mut cache_item = v as *mut cache_item;
    debug_decl!(SUDOERS_DEBUG_NSS!());

    let fresh15 = &mut (*item).refcnt;
    *fresh15 = (*fresh15).wrapping_sub(1);
    if *fresh15 == 0 as libc::c_int as libc::c_uint {
        free(item as *mut libc::c_void);
    }
    debug_return!();
}

#[no_mangle]
pub fn sudo_fakegrnam(mut group: *const libc::c_char) -> *mut group {
    let mut gritem: *mut cache_item_gr = std::ptr::null_mut::<cache_item_gr>();
    let mut item: *mut cache_item = std::ptr::null_mut::<cache_item>();
    let mut errstr: *const libc::c_char = std::ptr::null::<libc::c_char>();
    let mut gr: *mut group = std::ptr::null_mut::<group>();
    let mut len: size_t = 0;
    let mut name_len: size_t = 0;
    let mut i: libc::c_int = 0;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_NSS!());

        if grcache_bygid.is_null() {
            grcache_bygid = rbcreate(Some(
                cmp_grgid
                    as unsafe extern "C" fn(
                        *const libc::c_void,
                        *const libc::c_void,
                    ) -> libc::c_int,
            ));
        }
        if grcache_byname.is_null() {
            grcache_byname = rbcreate(Some(
                cmp_pwnam
                    as unsafe extern "C" fn(
                        *const libc::c_void,
                        *const libc::c_void,
                    ) -> libc::c_int,
            ));
        }
        if grcache_bygid.is_null() || grcache_byname.is_null() {
            sudo_warnx!(
                b"%s: %s\0" as *const u8 as *const libc::c_char,
                get_function_name!(),
                b"unable to allocate memory\0" as *const u8 as *const libc::c_char
            );
            debug_return_ptr!(std::ptr::null_mut::<group>());
        }

        name_len = strlen(group);
        len = (::std::mem::size_of::<cache_item_gr>() as libc::c_ulong)
            .wrapping_add(name_len)
            .wrapping_add(1 as libc::c_int as libc::c_ulong);

        i = 0 as libc::c_int;
        while i < 2 as libc::c_int {
            let mut grcache: *mut rbtree = std::ptr::null_mut::<rbtree>();
            let mut node: *mut rbnode = std::ptr::null_mut::<rbnode>();
            gritem = calloc(1 as libc::c_int as libc::c_ulong, len) as *mut cache_item_gr;

            if gritem.is_null() {
                sudo_warn!(
                    b"unable to cache group %s\0" as *const u8 as *const libc::c_char,
                    group
                );
                debug_return_ptr!(std::ptr::null_mut::<group>());
            }

            gr = &mut (*gritem).gr;
            (*gr).gr_gid = sudo_strtoid_v2(group.offset(1 as libc::c_int as isize), &mut errstr);
            let fresh19 = &mut (*gr).gr_name;
            *fresh19 = gritem.offset(1 as libc::c_int as isize) as *mut libc::c_char;
            memcpy(
                (*gr).gr_name as *mut libc::c_void,
                group as *const libc::c_void,
                name_len.wrapping_add(1 as libc::c_int as libc::c_ulong),
            );

            if !errstr.is_null() {
                sudo_debug_printf!(
                    SUDO_DEBUG_DIAG | SUDO_DEBUG_LINENO,
                    b"gid %s %s\0" as *const u8 as *const libc::c_char,
                    group,
                    errstr
                );
                free(gritem as *mut libc::c_void);
                debug_return_ptr!(std::ptr::null_mut::<group>());
            }

            item = &mut (*gritem).cache;
            (*item).refcnt = 1 as libc::c_int as libc::c_uint;
            (*item).d.gr = gr;

            if i == 0 as libc::c_int {
                (*item).k.gid = (*gr).gr_gid;
                grcache = grcache_bygid;
            } else {
                let fresh21 = &mut (*gritem).cache.k.name;
                *fresh21 = (*gr).gr_name;
                grcache = grcache_byname;
            }

            (*item).registry[0 as libc::c_int as usize] = '\u{0}' as i32 as libc::c_char;
            match rbinsert(grcache, item as *mut libc::c_void, &mut node) {
                1 => {
                    item = (*node).data as *mut cache_item;
                    if ((*item).d.gr).is_null() {
                        sudo_gr_delref_item(item as *mut libc::c_void);
                        let fresh22 = &mut (*node).data;
                        *fresh22 = &mut (*gritem).cache as *mut cache_item as *mut libc::c_void;
                        item = *fresh22 as *mut cache_item;
                    } else {
                        free(gritem as *mut libc::c_void);
                    }
                }
                -1 => {
                    sudo_warn!(
                        b"unable to cache group %s\0" as *const u8 as *const libc::c_char,
                        group
                    );
                    (*item).refcnt = 0 as libc::c_int as libc::c_uint;
                }
                _ => {}
            }
            i += 1;
        } // while

        if !((*item).d.gr).is_null() {
            let fresh23 = &mut (*item).refcnt;
            *fresh23 = (*fresh23).wrapping_add(1);
        }

        debug_return_ptr!((*item).d.gr);
    } //unsafe
}

#[no_mangle]
pub fn sudo_grlist_addref(mut grlist: *mut group_list) {
    unsafe {
        debug_decl!(SUDOERS_DEBUG_NSS!());
        let fresh26 = &mut (*((grlist as *mut libc::c_char).offset(-(40 as libc::c_ulong as isize))
            as *mut cache_item))
            .refcnt;
        *fresh26 = (*fresh26).wrapping_add(1);
        debug_return!();
    } //unsafe
}

unsafe extern "C" fn sudo_grlist_delref_item(mut v: *mut libc::c_void) {
    let mut item: *mut cache_item = v as *mut cache_item;
    debug_decl!(SUDOERS_DEBUG_NSS!());
    let fresh27 = &mut (*item).refcnt;
    *fresh27 = (*fresh27).wrapping_sub(1);
    if *fresh27 == 0 as libc::c_int as libc::c_uint {
        free(item as *mut libc::c_void);
    }
    debug_return!();
}

#[no_mangle]
pub fn sudo_grlist_delref(mut grlist: *mut group_list) {
    unsafe {
        debug_decl!(SUDOERS_DEBUG_NSS!());
        sudo_grlist_delref_item(
            (grlist as *mut libc::c_char).offset(-(40 as libc::c_ulong as isize)) as *mut cache_item
                as *mut libc::c_void,
        );
        debug_return!();
    } //unsafe
}

#[no_mangle]
pub fn sudo_freegrcache() {
    unsafe {
        debug_decl!(SUDOERS_DEBUG_NSS!());

        if !grcache_bygid.is_null() {
            rbdestroy(
                grcache_bygid,
                Some(sudo_gr_delref_item as unsafe extern "C" fn(*mut libc::c_void) -> ()),
            );
            grcache_bygid = std::ptr::null_mut::<rbtree>();
        }
        if !grcache_byname.is_null() {
            rbdestroy(
                grcache_byname,
                Some(sudo_gr_delref_item as unsafe extern "C" fn(*mut libc::c_void) -> ()),
            );
            grcache_byname = std::ptr::null_mut::<rbtree>();
        }
        if !grlist_cache.is_null() {
            rbdestroy(
                grlist_cache,
                Some(sudo_grlist_delref_item as unsafe extern "C" fn(*mut libc::c_void) -> ()),
            );
            grlist_cache = std::ptr::null_mut::<rbtree>();
        }
        if !gidlist_cache.is_null() {
            rbdestroy(
                gidlist_cache,
                Some(sudo_gidlist_delref_item as unsafe extern "C" fn(*mut libc::c_void) -> ()),
            );
            gidlist_cache = std::ptr::null_mut::<rbtree>();
        }

        debug_return!();
    } //unsafe
}

#[no_mangle]
pub fn user_in_group(mut pw: *const passwd, mut group: *const libc::c_char) -> bool {
    let mut grlist: *mut group_list = std::ptr::null_mut::<group_list>();
    let mut gidlist: *mut gid_list = std::ptr::null_mut::<gid_list>();
    let mut grp: *mut group = std::ptr::null_mut::<group>();
    let mut matched: bool = 0 as libc::c_int != 0;
    let mut i: libc::c_int = 0;

    unsafe {
        debug_decl!(SUDOERS_DEBUG_NSS!());

        'done: loop {
            if *group.offset(0 as libc::c_int as isize) as libc::c_int == '#' as i32 {
                let mut errstr: *const libc::c_char = std::ptr::null::<libc::c_char>();
                let mut gid: gid_t =
                    sudo_strtoid_v2(group.offset(1 as libc::c_int as isize), &mut errstr);
                if !errstr.is_null() {
                    sudo_debug_printf!(
                        SUDO_DEBUG_DIAG | SUDO_DEBUG_LINENO,
                        b"gid %s %s\0" as *const u8 as *const libc::c_char,
                        group,
                        errstr
                    );
                } else {
                    if gid == (*pw).pw_gid {
                        matched = 1 as libc::c_int != 0;
                        break 'done;
                    }
                    gidlist = sudo_get_gidlist(pw, 0 as libc::c_int as libc::c_uint);
                    if !gidlist.is_null() {
                        i = 0 as libc::c_int;
                        while i < (*gidlist).ngids {
                            if gid == *((*gidlist).gids).offset(i as isize) {
                                matched = 1 as libc::c_int != 0;
                                break 'done;
                            }
                            i += 1;
                        }
                    }
                }
            } //if

            if (*sudo_defs_table
                .as_mut_ptr()
                .offset(100 as libc::c_int as isize))
            .sd_un
            .flag
                != 0
            {
                let mut gid_0: gid_t = 0;
                grp = sudo_getgrnam(group);
                if grp.is_null() {
                    break 'done;
                }
                gid_0 = (*grp).gr_gid;

                if gid_0 == (*pw).pw_gid {
                    matched = 1 as libc::c_int != 0;
                    break 'done;
                }

                if gidlist.is_null() {
                    gidlist = sudo_get_gidlist(pw, 0 as libc::c_int as libc::c_uint);
                    if !gidlist.is_null() {
                        i = 0 as libc::c_int;
                        while i < (*gidlist).ngids {
                            if gid_0 == *((*gidlist).gids).offset(i as isize) {
                                matched = 1 as libc::c_int != 0;
                                break 'done;
                            } else {
                                i += 1;
                            }
                        }
                    }
                }
            } else if {
                grlist = sudo_get_grlist(pw);
                !grlist.is_null()
            } {
                //grlist = sudo_get_grlist(pw);
                let mut compare: Option<
                    unsafe extern "C" fn(*const libc::c_char, *const libc::c_char) -> libc::c_int,
                > = None;
                if (*sudo_defs_table
                    .as_mut_ptr()
                    .offset(114 as libc::c_int as isize))
                .sd_un
                .flag
                    != 0
                {
                    compare = Some(
                        strcasecmp
                            as unsafe extern "C" fn(
                                *const libc::c_char,
                                *const libc::c_char,
                            ) -> libc::c_int,
                    );
                } else {
                    compare = Some(
                        strcmp
                            as unsafe extern "C" fn(
                                *const libc::c_char,
                                *const libc::c_char,
                            ) -> libc::c_int,
                    );
                }

                i = 0 as libc::c_int;
                while i < (*grlist).ngroups {
                    if compare.expect("non-null function pointer")(
                        group,
                        *((*grlist).groups).offset(i as isize),
                    ) == 0 as libc::c_int
                    {
                        matched = 1 as libc::c_int != 0;
                        break 'done;
                    }
                    i += 1;
                }

                grp = sudo_getgrgid((*pw).pw_gid);
                if !grp.is_null()
                    && compare.expect("non-null function pointer")(group, (*grp).gr_name)
                        == 0 as libc::c_int
                {
                    matched = 1 as libc::c_int != 0;
                    break 'done;
                }

                /*if !grp.is_null() {
                    if compare.expect("non-null function pointer")(group, (*grp).gr_name)
                        == 0 as libc::c_int
                    {
                        matched = 1 as libc::c_int != 0;
                        break 'done;
                    }
                }*/
            }
            break 'done;
        } // end of done;
          //done

        if !grp.is_null() {
            sudo_gr_delref(grp);
        }
        if !grlist.is_null() {
            sudo_grlist_delref(grlist);
        }
        if !gidlist.is_null() {
            sudo_gidlist_delref(gidlist);
        }

        sudo_debug_printf!(
            SUDO_DEBUG_DEBUG,
            b"%s: user %s %sin group %s\0" as *const u8 as *const libc::c_char,
            get_function_name!(),
            (*pw).pw_name,
            if matched as libc::c_int != 0 {
                b"\0" as *const u8 as *const libc::c_char
            } else {
                b"NOT\0" as *const u8 as *const libc::c_char
            },
            group
        );
        //debug_return_bool!(matched as bool);
        debug_return_bool!(matched);
    } //unsafe
}
